package com.asiainfo.indb.view;

import com.asiainfo.indb.PanelUtil;
import com.asiainfo.indb.control.ThreadFactory;
import com.asiainfo.indb.control.db.DbTool;
import com.asiainfo.indb.model.FileGather;
import com.asiainfo.indb.model.InDbGather;
import org.apache.commons.lang3.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
 * @author zym
 * @date 2019-10-17 11:01
 */
public class TablePanel extends BaseTitlePanel implements ActionListener {

    /**
     * 列分隔符
     */
    public static final String COL_SPLIT = ",";

    /**
     * 该值表示删除该列
     */
    private static int DELETE_ORDER = -100;
    private JButton minus;
    private JButton plus;
    private JPanel btnPanel;
    private JTextField tableName;
    private ButtonGroup colBtnGroup;
    private JButton colBtn;

    public TablePanel(InDbPanel parentPanel) {
        super(parentPanel);
    }

    @Override
    protected String getPanelTitle() {
        return "入库表配置";
    }

    @Override
    protected void render(JPanel container) {
        container.setLayout(new BorderLayout());

        // 表名
        renderTableName(container);

        // 列名组
        renderColGroup(container);
    }

    private void renderColGroup(JPanel container) {
        JPanel titlePanel = new JPanel(new BorderLayout());
        titlePanel.setBorder(BorderFactory.createTitledBorder("列组（请按顺序添加）"));

        // 水平滚动
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        colBtnGroup = new ButtonGroup();
        btnPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));

        // 初始化-+
        minus = new JButton("-");
        minus.setBackground(Color.RED);
        minus.addActionListener(this);
        minus.setPreferredSize(new Dimension(30, 30));

        plus = new JButton("+");
        plus.setBackground(Color.GREEN);
        plus.addActionListener(this);
        plus.setPreferredSize(new Dimension(30, 30));

        btnPanel.add(minus);
        btnPanel.add(plus);

        scrollPane.setViewportView(btnPanel);
        titlePanel.add(scrollPane, BorderLayout.CENTER);
        container.add(titlePanel, BorderLayout.CENTER);
    }

    private void renderTableName(JPanel container) {
        tableName = new JTextField();
        tableName.setPreferredSize(new Dimension(tableName.getPreferredSize().width, 30));
        JPanel panel = PanelUtil.generateOneGridInputPanel("表名：", tableName, 4);

        colBtn = new JButton("获取列");
        colBtn.addActionListener(this);
        panel.add(colBtn, BorderLayout.EAST);

        container.add(panel, BorderLayout.NORTH);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof JButton) {
            JButton btn = (JButton) e.getSource();
            if (btn == minus) {
                minusCol();
            } else if (btn == plus) {
                plusCol();
            } else if (btn == colBtn) {
                InDbGather dbData = getCachedPanel(DbPanel.class).gather();
                if (dbData != null) {
                    String tn = tableName.getText();
                    if (StringUtils.isNotBlank(tn)) {
                        displayTableCols(tn, dbData);
                    } else {
                        PanelUtil.alert(getTopContainer(), "请输入表名");
                    }
                }
            } else {
                // 所有其他列按钮
                String desc = btn.getText();

                // 获取输入值
                String input = JOptionPane.showInputDialog(getTopContainer(), "调整列顺序（取消表示删除，-1、0和1都表示第一个）", "调整", JOptionPane.INFORMATION_MESSAGE);
                if (StringUtils.isBlank(input)) {
                    // 删除
                    reOrderCol(DELETE_ORDER, desc);
                } else if (StringUtils.isNumeric(input)) {
                    reOrderCol(Integer.parseInt(input), desc);
                }
            }
        }
    }

    /**
     * 显示表列
     *
     * @param tableName 表名
     * @param dbData    数据库信息
     */
    private void displayTableCols(String tableName, InDbGather dbData) {
        // 数据库查询
        // 此类耗时流程放到事件队列里去执行，防止假死
        // TODO loading界面
        PanelUtil.loading(this, "正在获取列信息...");
        ThreadFactory.run("getColThread", () -> {
            try {
                List<String> colList = DbTool.getTableCols(tableName, dbData);
                if (colList != null && colList.size() > 0) {
                    // 图形渲染队列
                    EventQueue.invokeLater(() -> renderCols(colList.toArray(new String[0])));
                }
            } catch (SQLException e) {
                PanelUtil.error(getTopContainer(), "获取列信息失败：" + e.getMessage());
            } finally {
                PanelUtil.endLoading(this);
            }
        });
    }

    /**
     * 重排列名
     *
     * @param order   当前列顺序
     * @param colName 列名
     */
    private void reOrderCol(int order, String colName) {
        if (colBtnGroup.getButtonCount() > 0) {
            List<String> preOrder = new ArrayList<>();
            Enumeration<AbstractButton> cols = colBtnGroup.getElements();
            while (cols.hasMoreElements()) {
                preOrder.add(cols.nextElement().getText());
            }

            if (order == DELETE_ORDER) {
                preOrder.remove(colName);
            } else {
                preOrder.remove(colName);
                if (order > preOrder.size()) {
                    preOrder.add(colName);
                } else if (order <= 1) {
                    preOrder.add(0, colName);
                } else {
                    preOrder.add(order - 1, colName);
                }
            }

            if (preOrder.size() > 0) {
                // 重新渲染
                renderCols(preOrder.toArray(new String[0]));
            } else {
                renderCols(null);
            }
        }
    }

    /**
     * 渲染列
     *
     * @param cols 列
     */
    private void renderCols(String[] cols) {
        btnPanel.removeAll();
        colBtnGroup = new ButtonGroup();

        // 渲染列
        if (cols != null) {
            for (String col : cols) {
                JButton button = new JButton(col.toUpperCase());
                button.addActionListener(this);
                button.setPreferredSize(new Dimension(button.getPreferredSize().width, 30));
                colBtnGroup.add(button);
                btnPanel.add(button);
            }
        }

        // 添加-+
        btnPanel.add(minus);
        btnPanel.add(plus);

        // 重新渲染
        btnPanel.validate();
        btnPanel.updateUI();
    }

    private void plusCol() {
        String colName = JOptionPane.showInputDialog(getTopContainer(), "请输入列名（大小写均可）", "新增列", JOptionPane.WARNING_MESSAGE);
        addCol(colName);
    }

    /**
     * 单个添加列，并单次渲染，所以请不要在循环内使用
     *
     * @param colName 列名
     */
    private void addCol(String colName) {
        if (StringUtils.isNotBlank(colName)) {
            JButton button = new JButton(colName.toUpperCase());
            button.setPreferredSize(new Dimension(button.getPreferredSize().width, 30));
            button.addActionListener(this);
            colBtnGroup.add(button);

            // 重新渲染列
            btnPanel.removeAll();
            Enumeration<AbstractButton> cols = colBtnGroup.getElements();
            while (cols.hasMoreElements()) {
                btnPanel.add(cols.nextElement());
            }

            // 添加-+
            btnPanel.add(minus);
            btnPanel.add(plus);

            btnPanel.validate();
            btnPanel.updateUI();
        }
    }

    private void minusCol() {
        int count = colBtnGroup.getButtonCount();
        if (count > 0) {
            // 重新渲染列
            btnPanel.removeAll();

            // 计算
            int index = 0;
            Enumeration<AbstractButton> cols = colBtnGroup.getElements();
            AbstractButton last = null;
            while (cols.hasMoreElements()) {
                if (++index >= count) {
                    // 最后一个不要了
                    last = cols.nextElement();
                } else {
                    btnPanel.add(cols.nextElement());
                }
            }

            colBtnGroup.remove(last);

            // 添加-+
            btnPanel.add(minus);
            btnPanel.add(plus);

            btnPanel.validate();
            btnPanel.updateUI();
        }
    }

    @Override
    public InDbGather gather() {
        InDbGather gather = new InDbGather();
        if (checkAndSetField("请输入表名", tableName, "TABLE_NAME", gather)) {
            if (colBtnGroup.getButtonCount() > 0) {
                boolean first = true;
                AbstractButton colBtn;
                StringBuilder builder = new StringBuilder();
                Enumeration<AbstractButton> btns = colBtnGroup.getElements();
                while (btns.hasMoreElements()) {
                    colBtn = btns.nextElement();
                    if (first) {
                        first = false;
                    } else {
                        builder.append(COL_SPLIT);
                    }

                    builder.append(colBtn.getText());
                }

                gather.put("TABLE_COLS", builder.toString());
                return gather;
            } else {
                PanelUtil.alert(getTopContainer(), "请添加入库文件对应的表列名");
            }
        }

        return null;
    }

    @Override
    public void initByFile(FileGather gather) {
        initField("TABLE_NAME", tableName, gather);

        if (gather != null) {
            String cols = gather.get("TABLE_COLS");
            if (StringUtils.isNotBlank(cols)) {
                renderCols(cols.split(TablePanel.COL_SPLIT));
            }
        }
    }
}